﻿//----------------------------------------------------------------
// Desc: 
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2009-10-15
//
// Update Date :            
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//----------------------------------------------------------------
#pragma once


#include "Base/FUI_Widget.h"


class FUI_Layout;


class FAPI FUI_Object : public IFUI_MemObject
{
    friend class FUI_Drawer;
    friend class FUI_System;
    friend class FUI_Frame;
    friend class FUI_Container;

    friend class FUI_SYS_DRAG_FRINGE;
    friend class FUI_SYS_DRAG_CTRL;

    friend class FU_RE_RICH;

protected:
    // 构造
    FUI_Object(EF_UI_WIDGET_TYPE t);
    // 运行
    virtual void Update();
    // 初始化数据
    virtual void InitUIData(FUI_Object* father, fuWidgetBase* pData, FUI_Layout* layout);

public:
    // 提供类仓库使用的
    const EF_UI_WIDGET_TYPE nTypeID;
    // 析构
    virtual ~FUI_Object();
    // 释放
    virtual void Release();
    // 设置是否可见
    virtual void SetVisible(bool bVis){ pWTData->SetVisible(bVis); }
    // 是否可见
    virtual bool IsVisible(){ return pWTData->IsVisible(); }
    // 设置可用
    virtual void SetEnable(bool enable){ pWTData->SetDisable(!enable); }
    // 是否有效的
    virtual bool IsEnable(){ return !pWTData->IsDisable(); }
    // 是否需要渲染
    virtual bool IsNeedRender(){ return IsVisible(); }
    // 屏幕真实坐标是否在本控件内
    virtual bool PtInObject(funit nX, funit nY);
    // 测试鼠标悬停在本控件内部（可能返回自己，可能返回自己的子控件）
    virtual FUI_Object* FindObject(funit nX, funit nY);
    // 指定控件是否是本对象的子控件（不含自己）
    virtual bool IsChild(FUI_Object* pChild){ return false; }
    // 设置自己坐标
    // .bReal 是表示相对于窗体的屏幕坐标，否则表示相对父的虚拟坐标
    virtual void SetPos(funit nX, funit nY, bool bReal);
    // 偏移自己虚拟坐标
    virtual void AddPos(funit nX, funit nY);
    // 设置显示宽度
    virtual void SetWidth(funit nW);
    // 设置显示高度
    virtual void SetHeight(funit nH);
    // 设置自己为焦点UI
    virtual bool SetActivate();
    // 自己是否是焦点UI
    virtual bool IsActivated();
    // 判断能否能使获得焦点
    virtual bool CanGetFocus(){ return IsVisible() && pWTData->IsCanFocus(); }
    // 设置能否获取焦点
    virtual void SetCanGetFocus(bool f){ pWTData->SetCanFocus(f); }
    // 获取是否有权限往外界传递消息
    virtual bool CanSendMessage(){ return pWTData->IsCanMessage(); }
    // 设置是否有权限往外界传递消息
    virtual void SetCanSendMessage(bool send){ pWTData->SetCanMessage(send); }
    // 取得控件拖拽能力
    virtual BYTE GetDragMode(){ return pWTData->nDragMode; }
    // 设置字体索引（编辑器中的预置字体索引）
    virtual void SetFontGroup(WORD nIndex);
    // 传递给用户界面消息
    virtual bool SendToLayout(EF_UI_EVENT_TYPE msgid, DWORD wParam = 0, DWORD lParam = 0);
    // 渲染时调用此函数以判断本控件有没有裁剪操作(如文本框没有边框而可以渲染出界、列表框有边框而不能渲染出界)
    virtual bool HasClip(){ return false; }
    // 渲染控件（由管理器自动处理层关系）（基础对象只使用了back和text层渲染）
    virtual void Render(EF_UI_RENDER_LAYER layer);
    // 自动刷新所有动态区域
    virtual void UpdateRect();
    // 设置显示文本
    virtual void SetText(const WCHAR* txt){ szDrawText = txt; }
    virtual void SetText(const ACHAR* txt){ szDrawText = txt; }
    // 获取显示文本
    virtual const WCHAR* GetText(){ return szDrawText.c_str(); }
    // 设置鼠标悬停提示文字
    virtual void SetTipText(const WCHAR* txt){ szTipsText = txt; }
    virtual void SetTipText(const ACHAR* txt){ szTipsText = txt; }
    // 获取鼠标悬停提示文字
    virtual const WCHAR* GetTipText(){ return szTipsText.c_str(); }
    // 取得宽度
    virtual funit GetWidth(){ UpdateRect(); return pWTData->uVirtualRect.uSize.nW; }
    // 取得高度
    virtual funit GetHeight(){ UpdateRect(); return pWTData->uVirtualRect.uSize.nH; }
    // 当前列表是否打开的（组合框专用的）
    virtual bool IsComboOpen(){ return false; }
    // 鼠标事件传递到Layout后如果不处理，控件自身处理LButton、RButton事件处理返回结果
    virtual bool GetCursorResult(EF_UI_EVENT_TYPE t){ return true; }
    // 键盘按下消息
    virtual bool OnKeyDown(unsigned int nChar);
    // 键盘松开消息
    virtual bool OnKeyUp(unsigned int nChar);
    // 字符消息
    virtual bool OnChar(unsigned int nChar);
    // 鼠标左键按下消息
    virtual bool OnLButtonDown(funit nX, funit nY);
    // 鼠标右键按下消息
    virtual bool OnRButtonDown(funit nX, funit nY);
    // 鼠标左键松开消息
    virtual bool OnLButtonUp(funit nX, funit nY);
    // 鼠标右键松开消息
    virtual bool OnRButtonUp(funit nX, funit nY);
    // 鼠标左键双击消息
    virtual bool OnLButtonDBClick(funit nX, funit nY);
    // 鼠标移动消息
    virtual bool OnMouseMove(funit nX, funit nY){ return false; }
    // 鼠标滚轮消息
    virtual bool OnMouseWheel(bool bUp, funit nX, funit nY){ return false; }
    // 控件获得了焦点
    virtual void OnGetFocus(){ SendToLayout(eUET_GetFocus, 0, 0); }
    // 控件失去了焦点
    virtual void OnLostFocus(){ SendToLayout(eUET_LostFocus, 0, 0); }
    // 鼠标移进了UI
    virtual void OnMoveIn();
    // 鼠标移出了UI
    virtual void OnMoveOut();
    // 鼠标拖拽出一个UI
    virtual void OnDragIn(FIDHASH nFrameID, FIDHASH nWidgetID){ SendToLayout(eUET_DragIn, nFrameID, nWidgetID);      }
    // 鼠标拖担忧进一个UI
    virtual void OnDragOut(FIDHASH nFrameID, FIDHASH nWidgetID){ SendToLayout(eUET_DragOut, nFrameID, nWidgetID);     }
    // 丢掉鼠标上的东西
    virtual void OnDragThrow(FIDHASH nFrameID, FIDHASH nWidgetID){ SendToLayout(eUET_DragThrow, nFrameID, nWidgetID);   }
    // 当框架隐藏的时候调用，用于清除滚动条等隐藏控件状态
    virtual void OnFrameHide(bool visable){}

public:
    // 取得控件的配置数据
    FINLINE const fuWidgetBase* GetCtrlData(){ return pWTData; }
    // 取得本控件的窗口的真实区域（整个控件的区域）
    FINLINE void GetRealRect(fuRect* prc){ UpdateRect(); *prc = uRealRect; }
    // 取得工作区（除去边框和边以后的区域，相对于窗体的坐标）
    FINLINE void GetWorkRect(fuRect* prc){ UpdateRect(); *prc = uWorkRect; }
    // 取得虚拟区域（与父之间的偏移区域）
    FINLINE void GetVirtualRect(fuRect* prc){ UpdateRect(); *prc = pWTData->uVirtualRect; }
    // 得到父控件（仅上一层）
    FINLINE FUI_Object* GetFather(){ return pFather; }
    // 得到控件 字符串 ID
    FINLINE const ACHAR* GetName(){ return pWTData->szName; }
    // 得到控件 DWORD ID
    FINLINE FIDHASH GetWidgetID(){ return pWTData->dwNameHash; }
    // 得到控件类型
    FINLINE EF_UI_WIDGET_TYPE GetType(){ return (EF_UI_WIDGET_TYPE)pWTData->nTypeID; }
    // 得到控件的对齐模式
    FINLINE EF_UI_ALIGN_MODE GetAlignMode(){ return (EF_UI_ALIGN_MODE)pWTData->nWidgetAlignMode; }
    // 得到字体颜色
    FINLINE DWORD GetFontColor(){ return pFontGroup->dwFontColor; }
    // 得到字体绘制效果
    FINLINE EF_UI_TEXT_EFFECT_TYPE GetFontEffect(){ return (EF_UI_TEXT_EFFECT_TYPE)pWTData->uFont.nEffectType; }
    // 得到字体效果颜色
    FINLINE DWORD GetEffectColor(){ return pFontGroup->dwEffectColor; }
    // 设置字体绘制模式
    FINLINE void SetFontEffectMode(EF_UI_TEXT_EFFECT_TYPE effect){ pWTData->uFont.nEffectType = (BYTE)effect; }
    // 最大化设置
    //FINLINE bool IsAlwaysHMax(){ return pWTData->IsAlwaysHMax(); }
    //FINLINE bool IsAlwaysVMax(){ return pWTData->IsAlwaysVMax(); }
    // 设置用户数据
    FINLINE void SetObjectData(DWORD_PTR data){ dwDataPtr = data; }
    // 取得用户数据
    FINLINE DWORD_PTR GetObjectData(){ return dwDataPtr; }
    // 得到显示文字体ID号
    FINLINE DWORD GetFontIndex(){ return pFontGroup->nFontIndex; }
    // 得到字符象素宽度（模糊宽度）
    FINLINE short GetCharWidth(){ return (short)(pFontGroup->nFontSize>>1); }
    // 得到字符象素高度（模糊宽度）
    FINLINE short GetCharHeight(){ return (short)pFontGroup->nFontSize; }
    // 设置在最新坐标前必须刷新区域坐标信息
    FINLINE void NeedUpdateRect(){ bNeedRefRect = true; }
    // 获取我的管理器相关地址
    FINLINE FUI_System* GetMyUIMgr(){ return pUIMgr; }
    FINLINE FUI_Layout* GetMyLayout(){ return pUILayout; }
    FINLINE FUI_Object* GetMyFather(){ return pFather; }

public:
    // 设置背景底图
    bool SetBackPicture(FIDHASH res_hash, FIDHASH pic_hash);
    // 取得某条边边缘方向上否可以拖动尺寸
    bool CanFringeDrag(BYTE fringe);
    // 取得边缘框区域(prc[4]=上下左右)
    bool GetFringeRect(fuRect* prc);
    // 得到父区域
    void GetFatherRect(fuRect* prc);
    // 取得我的根框架地址
    FUI_Frame* GetFrameData();
    // 取得根框架ID
    FIDHASH GetFrameID();
    // 用参数绘制字符串，其它参数使用控件本身的设置
    void DrawString(fuRect* rc, const WCHAR* pstring, BYTE flags);
    void DrawString(fuRect* rc, const WCHAR* pstring, DWORD color, BYTE flags);
    void DrawStringEx(funit x, funit y, const WCHAR* pstring);
    void DrawStringEx(funit x, funit y, const WCHAR* pstring, DWORD color);
    // 快速设置文本
    void SetText(int n);
    void SetText(float n);

protected:
    FUI_System*         pUIMgr;         // 我的管理器地址
    FUI_Layout*         pUILayout;      // 我的框架地址
    FUI_Object*         pFather;        // 父控件
    fuWidgetBase*       pWTData;        // 我的控件数据
    fuFontGroup*        pFontGroup;     // 字体数据
    fuRect              uRealRect;      // 真实屏幕坐标区域
    fuRect              uWorkRect;      // 除去边框后的工作区域（屏幕区域）
    DWORD_PTR           dwDataPtr;      // 控件用户数据
    FUI_StringW         szTipsText;     // Tips 多语言文本
    FUI_StringW         szDrawText;     // 显示在控件上面的文字
    bool                bNeedRefRect;   // 是否必须刷新区域
};
typedef FUI_Vector< FUI_Object* > FV_UI_POBJECT;